# -*- coding: UTF-8 -*-
# *******************************************************************
# File Name: timer
# > Author: 04000387
# > Created Time: 2023/11/22 8:47
# *******************************************************************

import time
import datetime


def sort_timestamp(timestamp):
    res = sorted(timestamp, key=lambda x: x[0] * 3600 + x[1] * 60 + x[2])
    return res


def format_number(num, bit_num=2):
    s = str(num)
    if len(s) > bit_num:
        raise "number's bit longer than max bit"

    s = s if len(s) == bit_num else "0" * (bit_num - len(s)) + s
    return s


def get_day():
    now = datetime.datetime.now()
    year = now.year
    month = now.month
    day = now.day
    s = str(year) + "-"
    s += "-".join(map(format_number, [month, day]))
    return s


def get_hour_min():
    struct_time = time.localtime()

    return struct_time.tm_hour, struct_time.tm_min, struct_time.tm_sec


def decode_timestamps(timestamps):
    res = []
    for it in timestamps:
        res.append(list(map(int, it.split(":"))))

    return res


def re_format_date(date: str):
    r = date.split("-")
    date = r[0] + "-"
    date += "-".join(map(format_number, r[1:]))
    return date


class Timer:
    """
    程序计时执行.
    timestamps: 执行的时段->['12:30:11','13:40:00']
    rests: 暂停执行的日期->['2023-11-06', '2023-09-01']
    log:保存日志的路径,如果是None则不保存路径
    """

    def __init__(self, timestamps, rests=None, log=None):
        self.timestamps = sort_timestamp(decode_timestamps(timestamps))
        self.rests = rests
        self.log = log

    def cal_sec(self, i):
        now = get_hour_min()
        ret = ((self.timestamps[i][0] - now[0]) * 3600 +
               (self.timestamps[i][1] - now[1]) * 60 + self.timestamps[i][2] - now[2])

        ret = ret if ret > 0 else 24 * 3600 + ret

        return ret

    def get_idx(self):
        now = get_hour_min()
        # 默认是0
        idx = 0
        for i in range(len(self.timestamps)):
            if self.timestamps[i][0] < now[0]:
                continue

            if self.timestamps[i][0] == now[0] and self.timestamps[i][1] < now[1]:
                continue

            if (self.timestamps[i][0] == now[0] and self.timestamps[i][1] == now[1] and self.timestamps[i][2]
                    <= now[2] + 1):
                continue
            idx = i
            break

        return idx

    def write_log(self, strs, flag):

        with open(self.log, "a", encoding="utf-8") as fp:
            if flag:
                fp.write(datetime.datetime.now().strftime("%Y-%M-%d %H:%M:%S") + ":\n")
            fp.write(strs + "\n")
            if flag:
                fp.write("=" * 50 + "\n")

    def __call__(self, fun):
        def wrapper(*args, **kwargs):
            i = self.get_idx()
            delay = self.cal_sec(i)
            while True:
                s = "据下次执行还有{}秒,程序执行返回值\n".format(delay)
                if self.log is not None:
                    self.write_log(s, False)

                time.sleep(delay)
                flag = True
                # set date not execute the function
                if self.rests is not None and get_day() in self.rests:
                    flag = False

                if flag:
                    ret = fun(*args, **kwargs)
                    if self.log is not None:
                        s += str(ret)
                        self.write_log(s, True)

                i = (i + 1) % len(self.timestamps)
                delay = self.cal_sec(i)

        return wrapper


if __name__ == "__main__":
    times = ["10:33:00", "10:34:40", "10:38:23"]
    rest = ["2023-11-22"]


    @Timer(times, rest, "./log.txt")
    def fun(a, b):
        return a + b


    fun(10, 20)
